08. Exercise: Add View Interactivity

21 6 AAK Custom Views Interactivity Slide-SC V2

Reflect

QUESTION:

Why do you override performClick()? What happens if you override onClickListener() instead?

ANSWER:

The performClick() method calls onClickListener(). If you override performClick(), another contributor can still override onClickListener(). For example, if you create a custom view and make it available through a library for use or subclassing, its user can add their own click handling through onClickListener().

Exercise

In this exercise you are going to add interactivity to the view.

  1. In DialView.kt, inside the FanSpeed enumeration, add an extension function next() that changes the current fan speed to the next speed in the list (from OFF to LOW, MEDIUM, and HIGH, and then back to OFF). The complete enumeration now looks like this:
private enum class FanSpeed(val label: Int) {
   OFF(R.string.fan_off),
   LOW(R.string.fan_low),
   MEDIUM(R.string.fan_medium),
   HIGH(R.string.fan_high);

   fun next() = when (this) {
       OFF -> LOW
       LOW -> MEDIUM
       MEDIUM -> HIGH
       HIGH -> OFF
   }
}
  1. Inside the DialView class, just before the onSizeChanged() method, add an init() block. Setting the view's isClickable property to true enables that view to accept user input.
init {
   isClickable = true
}
  1. Below init(), override the performClick() method with this code:
override fun performClick(): Boolean {
   if (super.performClick()) return true

   fanSpeed = fanSpeed.next()
   contentDescription = resources.getString(fanSpeed.label)

   invalidate()
   return true
}
  • The call to super.performClick() must happen first, which enables accessibility events as well as calls onClickListener().

  • The next two lines increment the speed of the fan with the next() method, and set the view's content description to the string resource representing the current speed (off, 1, 2 or 3).

  • Finally, the invalidate() method invalidates the entire view, forcing a call to onDraw() to redraw the view. If something in your custom view changes for any reason, including user interaction, and the change needs to be displayed, call invalidate().

  1. Run the app.
  2. Tap the DialView element to move the indicator from off to 1. The dial should turn green.
  3. With each tap, the indicator should move to the next position.
  4. When the indicator returns to off, the dial should turn gray again.